/****************************************************************************************
*            . .. .                                                                     *
*                    ...                                                                *
*                       .":                                                             *
*   .                      u                                                            *
* ..     .:uxkkOkkx=.      "k'                                                          *
*.     "k00O0ko==uk00x'     OO.                       IBE-CAE                           *
*'   .xK0O00: 'xx" x0Ku    .O0:     Copyright (C) by Internet Based Engineering         *
*   .O0OO00= oKOk:"O0O'    :00=                 All rights reserved.                    *
*.  =0OOO00" =OOO0Oo'     =0OO:                      www.ibe.cn                         *
*.  u0OOOO0O'          .o00OOO.                                                         *
* . :KOOOOO00xu=:::=uok00OOOO"                                                          *
*   .x00OOOOOO0000000OOOOOOx.                                                           *
*    .u00OOOOOOOOOOOOOOOOO=                                                             *
*      .ukOOOOOOOOOOOOku'                                                               *
*          .'::==::'.                                                                   *
****************************************************************************************/

#ifndef IBE_MESHS_H_
#define IBE_MESHS_H_

#include <string>

#include "IBE_Object.h"

namespace ibe_common
{
    /**
     * @class IBE_Meshs
     * @brief 存储网格信息
     * @author liupeng
     */
    class IBE_COMMON_EXPORT IBE_Meshs : public IBE_Object
    {
    public:
        explicit IBE_Meshs();
        ~IBE_Meshs();

        IBE_TypeMacro( ibe_common, IBE_Meshs, ibe_common, IBE_Object );

        virtual void Initialize() override;
        virtual void InitPoints();
        virtual void InitCells();

        //@{
        /**
         * @brief 设置/获取版本信息
         *
         * @param ver 版本信息，默认2.0
         * @return 版本信息
         */
        virtual void SetVersion( const char* ver );
        virtual const char* GetVersion();
        //@}

        //@{
        /**
        * @brief 网格数据类型
        */
        enum IBE_MeshType
        {
            IBE_MESH_UNKNOWN = 0,       //!< 未知网格类型
            IBE_MESH_UNSTRUCTURED_VTK,  //!< vtk非结构网格，VTK_UNSTRUCTURED_GRID
            IBE_MESH_STRUCTURED_VTK     //!< vtk结构网格，VTK_STRUCTURED_GRID
        };
        /**
         * @brief 设置/获取网格数据类型
         *
         * @param meshType IBE_Enum::IBE_MeshType枚举值
         */
        virtual void SetMeshType( const int meshType );
        virtual int GetMeshType();
        //@}

        //@{
        /**
         * @brief 设置点坐标
         *
         * @param numOfPoints 点数
         * @param points 长度为numOfPoints*3，连续3个数值表示一个点
         */
        virtual void SetPoints( const int64_t numOfPoints, float* points );
        /**
         * @brief 添加单个点坐标
         *   
         * @param x 点坐标x值
         * @param y 点坐标y值
         * @param z 点坐标z值
         * @param xyz 点坐标x、y、z值
         * @return 新加点坐标的索引
         */
        virtual int64_t AddPoint( const float x, const float y, const float z);
        virtual int64_t AddPoint( float* xyz );
        /**
         * @brief 添加多个点坐标
         *   
         * @param pointSize 新加点坐标个数
         * @param points 新加点坐标，长度为pointSize*3，连续3个数值表示一个点
         */
        virtual void AddPoints( const int64_t pointSize, float* points );
        virtual int64_t GetNumberOfPoints()
        {
            return this->numOfPoints_;
        }
        /**
         * @brief 获取所有点坐标
         *
         * @param p 传入用来接收所有点坐标的数组
         * @return 所有点的坐标
         */
        virtual void GetPoints( float* p );
        virtual float* GetPoints();
        /**
         * @brief 根据点id获取点坐标
         *
         * @param pointId 点id，从0开始
         * @param point 接收点坐标的数组float point[3]
         * @return 返回对应的点坐标，用完需要delete
         */
        virtual void GetPoint( const int64_t pointId, float* point );
        virtual float* GetPoint( const int64_t pointId );
        //@}

        //@{
        /**
         * @brief 设置单元信息
         *
         * @param numOfCells 单元数
         * @param cellTypes 单元类型数组，长度为numOfCells
         * @param cellConnectivity 单元数据数组
         * 内容为：numPts0,id1,id2, numPts1,id1,id2,id3 ...
         * 其中numPts表示单元中有几个节点，numPts后面表示单元中节点的顺序
         * @param faces polyhedron（多面体）单元的单元面数据，没有polyhedron单元则没有此数据
         * 内容为：numCellFaces1,numFace0Pts,id1,id2,id3,numFace1Pts,id1,id2,id3, numCellFaces2,numFace0Pts,id1 ...
         * 其中，numCellFaces1和numCellFaces2表示单元有几个面，numFacePts表示单元每个面有几个节点，numFacePts后面的数字表示单元面中节点的顺序
         * @param materials 单元的材料编号（如0,1,2之类,-1表示没有），长度为numOfCells
         */
        virtual void SetCells( const int64_t numOfCells, uint8_t* cellTypes, int64_t* cellConnectivity,
                               int64_t* faces = nullptr, int* materials = nullptr );
        /**
         * @brief 添加多个单元信息
         */
        virtual void AddCells( const int64_t numOfCells, uint8_t* cellTypes, int64_t* cellConnectivity,
                               int64_t* faces = nullptr, int* materials = nullptr );
        /**
         * @brief 添加单个单元信息
         */
        virtual void AddCell( uint8_t cellType, int64_t* cellConnectivity,
                              int64_t* faces = nullptr, int material = 0 );
        virtual int64_t* GetCellConnectivity()
        {
            return this->cellConnectivity_;
        }
        virtual int64_t GetCellConnectivitySize()
        {
            return this->cellConnectivitySize_;
        }
        virtual int64_t GetNumberOfCells();
        virtual void GetCellTypes( uint8_t* types );
        virtual uint8_t* GetCellTypes();
        virtual uint8_t GetCellType( const int64_t cellId );
        /**
         * @brief 获取单元中节点的数量
         *
         * @param cellId 单元id
         * @return 节点数
         */
        virtual int64_t GetPointsCountOfCell( const int64_t cellId );
        /**
         * @brief 根据单元id获取对应的单元数据
         *
         * @param cellId 单元id
         * @return 格式：[id1,id2 ...]
         */
        virtual int64_t* GetCell( const int64_t cellId );
        /**
         * @brief 获取单元偏移量
         *
         * @return 单元偏移量数组，长度为numOfCells
         */
        virtual int64_t* GetCellOffsets();
        /**
         * @brief 获取polyhedron（多面体）单元面数据
         *
         * @return 所有polyhedron的面数据
         */
        virtual int64_t* GetCellFaces();
        virtual int64_t GetCellFaceSize();
        virtual int64_t* GetCellFaceOffsets();
        virtual int64_t GetCellFaceOffsetSize();
        /**
         * @brief 设置/获取单元材料
         *
         * @param materialSize materials数组长度
         * @param materials 单元的材料编号（如0,1,2之类,-1表示没有）
         * @return 长度为numOfCells
         */
        virtual void SetMaterials( int materialSize, int* materials );
        virtual int* GetMaterials();
        virtual int GetMaterial( const int64_t cellId );
        //@}

        //@{
        virtual void SetTraversalLocation( const int64_t location );
        virtual int64_t GetTraversalLocation()
        {
            return this->traversalLocation_;
        }
        //@}

        virtual void Copy( ibe_common::IBE_Object* obj ) override;

    protected:
        std::string version_; //!< 版本信息，默认“2.0”
        int meshType_; //!< 网格的数据类型，默认为IBE_Enum::IBE_MeshType
        int64_t numOfPoints_; //!< 点数
        float* points_; //!< 点坐标，长度为numOfPoints*3，连续3个数值表示一个点
        int64_t numOfCells_; //!< 单元数
        uint8_t* cellTypes_; //!< 单元类型数组，cellType为vtkCellType中的vtk单元类型（如VTK_VERTEX、VTK_LINE等），长度为numOfCells
        int64_t cellConnectivitySize_;  //!< cellConnectivity_数组长度
        int64_t* cellConnectivity_; //!< 存储单元的节点，内容为：numPts0,id1,id2, numPts1,id1,id2,id3 ...
                                   //!< 其中，numPts表示单元中有几个节点，numPts后面表示单元中节点的顺序
                                   //!< （非polyhedron单元和polyhedron单元一致）
        int64_t* cellOffsets_; //!< cellConnectivity_中numPts的索引号
        int64_t traversalLocation_; //!< vtkCellArray中GetNextCell方法中用来定位当前获取cell的位置，默认为0
        int64_t* cellFaces_; //!< polyhedron（多面体）单元的单元面数据，没有polyhedron单元则没有此数据
                            //!< 内容为：numCellFaces1,numFace0Pts,id1,id2,id3,numFace1Pts,id1,id2,id3, numCellFaces2,numFace0Pts,id1 ...
                            //!< 其中，numCellFaces1和numCellFaces2表示单元有几个面，numFacePts表示单元每个面有几个节点，
                            //!< numFacePts后面的数字表示单元面中节点的顺序
        int64_t cellFaceSize_; //!< cellFaces的长度
        int64_t* cellFaceOffsets_; //!< polyhedron（多面体）单元独有的数据，没有polyhedron单元则没有此数据
                                  //!< 内容为：-1，index1，-1，index2 ...
                                  //!< 其中，长度为numOfCells，-1表示cells中第一个单元是非polyhedron单元，
                                  //!< index1、index2分别表示numCellFaces1、numCellFaces2在cellFaces中的索引
        int64_t cellFaceOffsetSize_; //!< cellFaceOffsets_的长度
        int* materials_; //!< 单元的材料编号（如0,1,2之类,-1表示没有），长度为numOfCells

    private:
        IBE_Meshs( const IBE_Meshs& ) = delete;
        IBE_Meshs& operator=( const IBE_Meshs& ) = delete;
    };
} // namespace ibe_common

#endif // IBE_MESHS_H_